package Sokoban;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class RunnableMyFrame extends Frame implements ComponentListener, ActionListener, KeyListener, Runnable{
	
	MapObject firstMap;
	MapObject currentMap;
	RunnableGetImage Board;
	ChoiceButtons choiceButtons;
	
	ConnectionButtons connectionButtons;
	BufferStrategy bs = null;
	int tile_size=0;
	DescriptionPanel p1;
	Thread t = null;
	int seconds = 0;
	int levelNo = 1;
	int trialNo = 0;
	int totalLevelsNo = 0;
	int maxSeconds = 0;
	int maxTrials = 0;
	private boolean levelCompleted = false;
	static boolean gameFailed = false;
	String mapFileName = "map" + levelNo + ".txt";
	static boolean gameCompleted = false;
	private int result = 0;
	private boolean rankingUpdated = false;
	public static int numOfScores;
	private boolean gameStarted = false;
	RunnableMyFrame(String title) throws IOException{
		
	    super(title);
	    
		Scanner s = null;
        
		
        try {
        	
            s = new Scanner(new BufferedReader(new FileReader("Config.txt")));
            s.nextLine();
            tile_size=s.nextInt();
            s.nextLine();
            s.nextLine();
            totalLevelsNo = s.nextInt();
            s.nextLine();
            s.nextLine();
            maxTrials = s.nextInt();
            s.nextLine();
            s.nextLine();
            maxSeconds = s.nextInt();
            s.nextLine();
            s.nextLine();
            numOfScores = s.nextInt();
            
        
        }
        
        finally {
            s.close();
        }
    
		setBackground(Color.gray);
        seconds = maxSeconds;
        trialNo = maxTrials;
        choiceButtons = new ChoiceButtons();
        connectionButtons = new ConnectionButtons();
        //Board = getNewBoard();
       
        p1 = new DescriptionPanel();
		
		
		
		add(p1, "South");
		//add(Board, "North");
		add(connectionButtons, "North");
		 
		pack();
		
		addKeyListener(this);
		addComponentListener(this);
		connectionButtons.localButton.addActionListener(this);
		connectionButtons.netButton.addActionListener(this);
		choiceButtons.nextButton.addActionListener(this);
		choiceButtons.restartButton.addActionListener(this);
		
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent we) {
				System.out.println("Trwa zamykanie okna");
				Thread.currentThread().interrupt();
				if (rankingUpdated == true) System.exit(0);
				
				else 
				{
					Ranking.makeRanking(levelNo, result);
					System.exit(0);
				}
				//System.setProperty("sun.awt.noerasebackground", "false");
				//dispose();	
			}
		});
		
		
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				//if (isVisible()) repaint();
				setVisible(true);
				//if(isShowing()) repaint();
				//requestFocus();
				 //System.setProperty("sun.awt.noerasebackground", "true");
			}
		});
	}//end of constructor
		
	private synchronized void getNewBoard() throws IOException 
	{
		System.out.println("Jestem w funkcji tworzacej mape");
		if (Main.internetConnection)
			{
				if (firstMap == null) 
					{
						firstMap = getMap();
					
						Board = new RunnableGetImage(firstMap, tile_size, bs);
					}
			
				else 
					{
						currentMap = getMap();
					
						Board = new RunnableGetImage(currentMap, tile_size, bs);
					}
				
			}
		else 
			{
				if (firstMap == null) 
					{
					System.out.println("Jestem w funkcji tworzacej pierwsza mape");
						firstMap = new MapObject(mapFileName);
						
						Board = new RunnableGetImage(firstMap, tile_size, bs);
					}
				else 
					{
					System.out.println("Jestem w funkcji tworzacej obecna mape");
						currentMap = new MapObject(mapFileName);
						
						Board = new RunnableGetImage(currentMap, tile_size, bs);
					}
		
			}
		
	}

	private MapObject getMap() {
		// metoda zwróci obiekt poprany z sieci
		return null;
	}

	public void run() 
    {
	//long StartTime = System.currentTimeMillis(); 
    //Thread.currentThread().setPriority(Thread.NORM_PRIORITY - 1);
	System.out.println("My thread started");
		
	while (trialNo>0){
   requestFocus();
    do
    	{
    		if (RunnableGetImage.completed)
    			{
    				
    				levelCompleted = true;
    				if (levelNo==totalLevelsNo) 
    					{
    					gameCompleted = true;
    					removeKeyListener(this);
    					Ranking.makeRanking(levelNo, result);
    					rankingUpdated=true;
    					showSuccess(getWidth(), getHeight());
    					System.out.println("Zakończyłeś poziom!");
        				Thread.currentThread().interrupt();
        				return;
    					}
    				
    				System.out.println("Zakończyłeś poziom!");
    				Thread.currentThread().interrupt();
    				
    				showChoice();
    				repaint();
    				return;
    				//add(Board);
    				//Board.repaint();
    				//p2.repaint();
    				/*remove(Board);
    				add(MyButtons);
    				MyButtons.repaint();*/
    				
    				
    				
    			}
    		
       
    	
    		p1.updateDescription(seconds, trialNo, levelNo);
    		seconds-=1;
    		result++;
    	
    		try
    			{
    				Thread.sleep(1000);
    			}
    		catch (InterruptedException e) {}
    	} while (seconds>0);
    
    trialNo-=1;
    seconds=maxSeconds;
    if (trialNo>0) 
    	{	
    		mapFileName = "map" + levelNo + ".txt";
    		try
    			{
    				restartLevel();
    			}
    		catch (IOException e)
    		{
    			System.out.println(e.getMessage());
    		}
    	}
    //powinno byc info nacisnij r aby rozpoczac ponownie
    
    
    //repaint();
	}
	seconds=0;
	p1.updateDescription(seconds, trialNo, levelNo);
    gameFailed = true;
    showFailure(getWidth(), getHeight());
    //add(Board);
    //p2.repaint();
    //Board.setVisible(false);
    //add(choiceButtons.restartButton);
    //pack();
    //removeKeyListener(this);
    //render();
    //_fireStateEvent();
	   
    }
	
	private void showSuccess(int width, int height) {
		
		
		removeAll();
		repaint();
		revalidate();
		setSize(new Dimension(width, height));
		add(new Label("Ukończyłś grę. Twój wynik został wpisany do rankingu"));
		pack();
		
	}

	private void showFailure(int width, int height) {
		
		
		removeAll();
		repaint();
		revalidate();
		setSize(new Dimension(width, height));
		Panel p1 = new Panel(new GridLayout());
		p1.add(new Label("Niestety przegrałeś. Naciśnij przysisk, żeby zrestartować grę"));
		p1.add(choiceButtons.restartButton);
		choiceButtons.restartButton.setVisible(true);
		add(p1, "Center");
		pack();
		
	}

	/*private void makeRanking() {
		
		File file = new File("Ranking.txt");
		String output = levelNo + " " + result ;
		try {
			file.createNewFile();
		
			FileWriter fileWriter = new FileWriter(file.getName(), true);
			BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
			bufferedWriter.write(output);
			bufferedWriter.newLine();
			
			bufferedWriter.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("Błąd I/O");
		}
		
	}*/
	private void showChoice() {
		
		//remove(Board);
		System.out.println("Jestem w showChoice"); 
		removeAll();
		repaint();
		revalidate();
		//Board.setVisible(true);
		add(choiceButtons, "North");
		choiceButtons.nextButton.setVisible(true);
		choiceButtons.restartButton.setVisible(true);
		pack();
		requestFocus();

	}



	private synchronized void restartLevel() throws IOException 
		{
			requestFocus();
			remove(Board);
			getNewBoard();
			add(Board,"North");
			//choiceButtons.setVisible(true);
		    p1.updateDescription(seconds, trialNo, levelNo);
		    add(p1,"South");
		    System.out.println("Zrestartowałem poziom");
		    repaint();
		    pack();
		}
	
	private synchronized void restartGame() {
		
		removeAll();
		repaint();
		revalidate();
		/*if (choiceButtons.restartButton.isVisible()) choiceButtons.restartButton.setVisible(false);
		if (choiceButtons.nextButton.isVisible()) choiceButtons.nextButton.setVisible(false);
		if (connectionButtons.netButton.isVisible()) connectionButtons.netButton.setVisible(false);
		if (connectionButtons.localButton.isVisible()) connectionButtons.localButton.setVisible(false);*/
		requestFocus();
		levelNo = 1;
		seconds = maxSeconds;
		trialNo = maxTrials;
		mapFileName = "map1.txt";
		try
			{
				getNewBoard();
			}
		catch (IOException e)
			{
				System.out.println(e.getMessage());
			}
		
		p1.updateDescription(seconds, trialNo, levelNo);
		
		add(Board, "North");
		add(p1, "South");
		//validate();
		pack();
		//(t = new Thread(this)).start();
		System.out.println("Zrestartowałem grę");
		
	}

	private void advanceLevel() 
	
		{
		
			
					levelNo++;
					seconds = maxSeconds;
					trialNo = maxTrials;
					mapFileName = "map" + levelNo + ".txt";
					remove(choiceButtons);
					revalidate();
					try
					{
						getNewBoard();
					}
				    catch (IOException e)
					{
						System.out.println(e.getMessage());
					}
					p1.updateDescription(seconds, trialNo, levelNo);
					
					add(Board, "North");
					add(p1,"South");
					pack();
					
					System.out.println("Kolejny poziom");
		
		
			}
	
		//}
		
	public void update(Graphics g)
	
		{
		
			System.out.println("Jestem w update nalezacym do Frame");
			paint(g);

			
		}
	
	public void paint(Graphics g)
	
		{
		
			System.out.println("Jestem w paint nalezacym do Frame");
			super.paint(g);
					
		}

		/*addComponentListener(new ComponentAdapter() {
			public void componentResized(ComponentEvent ce){
				
				int height = ce.getComponent().getHeight();
				int width = ce.getComponent().getWidth();
				Board.TILE_SIZE=Math.min(width/(Board.getMap().getWidth()),height/(Board.getMap().getWidth()));
				BufferStrategy bs = Board.bs;
				do {
	            	
	            	do {
	            		
	            		Graphics graphics = bs.getDrawGraphics();
	            		Board.paint(graphics);
	            		
	            		graphics.dispose();

	            		
	    	         } while (bs.contentsRestored());
	            	
	            	bs.show();
	            	
		     	} while (bs.contentsLost());*/
		
	
	/*public Dimension getPreferredSize() {
		//System.out.println(getClass().getName() + ".getPreferredSize() called");
		return new Dimension(new Dimension(p1.getWidth(), Board.getMap().getHeight()*Board.TILE_SIZE + 3*(p1.getHeight())));*/
	
	/*public void validate() {
	    super.validate();
	    new_size.width = getWidth();
	    new_size.height = getHeight();
	    if (old_size.equals(new_size)) {
	        return;
	    } else {
	        render();
	    }
	}*/

	/*public void paint(Graphics g) {
	    super.paint(g);
	    //System.out.println("Paint działa.");
	    /*if(endOfGame){
	    	System.out.println("Przegrałeś");
	    g.clearRect(0, 0, getWidth(), getHeight());
	    }*/
	
	
	public void addNotify() {
        super.addNotify();
        requestFocus();
        //System.setProperty("sun.awt.noerasebackground", "true");
        createBufferStrategy(2); // argumentem liczba buforów
        bs = getBufferStrategy();
        System.out.println("Jestem w addnotify");
        /*Image offscr = createImage(getWidth(), getHeight());
        Graphics offgr = offscr.getGraphics();*/
        /*offscr = createImage(getPreferredSize().width,
                getPreferredSize().height);
         = offscr.getGraphics();*/
    }
	
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyReleased(KeyEvent e) {
		
		int c=e.getKeyCode();
		//MyEventQueue.begin=false;
		//if (RunnableGetImage.begin){
		if (!gameFailed & !levelCompleted){
		
		if (c == KeyEvent.VK_UP) {
			System.out.println("VK_UP pressed");
			//float initialPosition = Board.getMap().getPlayer().getY();
			//System.out.println(initialPosition);
		
			{
			try {
				
				Board.moveUp();
				
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			}
			
		} else if (c == KeyEvent.VK_DOWN) {
			
			System.out.println("VK_DOWN pressed");
			
			try {
			
				Board.moveDown();
			
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
			
		} else if (c == KeyEvent.VK_LEFT) {
			
			System.out.println("VK_LEFT pressed");
			
			try {
				Board.moveLeft();
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
				
				
		} else if (c == KeyEvent.VK_RIGHT) {
			
			System.out.println("VK_RIGHT pressed");
			 //Plansza nie reaguje na wciskanie klawiszy
			try {
				Board.moveRight();
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			}
		}
		/*else if (c == KeyEvent.VK_R) {
				gameFailed=false;
				levelCompleted=false;
				RunnableGetImage.completed=false;
				restartGame();
		}
		else if (c==KeyEvent.VK_N) {
				RunnableGetImage.completed = false;
				levelCompleted=false;
				advanceLevel();
		}*/
		
    }
		//MyEventQueue.begin=true;
		
    
    
		

	
	

	/*public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}*/

	
	/*public void componentHidden(ComponentEvent arg0) {
		// TODO Auto-generated method stub
		
	}*/

	/*public void componentMoved(ComponentEvent arg0) {
		// TODO Auto-generated method stub
		
	}*/


	public void componentResized(ComponentEvent ce) {
		if (!gameFailed & !levelCompleted & gameStarted)
		{
		bs = Board.bs;
		double size = (double)getWidth()/Board.getMap().getWidth();
		//tile_size = (int) size;
		Board.TILE_SIZE = (int) size;
		
		do {
        	// The following loop ensures that the contents of the drawing buffer
        	// are consistent in case the underlying surface was recreated
        	do {
        		// Get a new graphics context every time through the loop
        		// to make sure the strategy is validated
        		Graphics graphics = bs.getDrawGraphics();
        		Board.updateOffscreen(graphics);
        		//repaint((int)(initialPosition)*TILE_SIZE, (int)(map.getPlayer().getY())*TILE_SIZE, 3*64, 64);//updateOffscreen(graphics);// Render to graphics sprobowac repaintem
        		graphics.dispose(); // Dispose the graphics

        		// Repeat the rendering if the drawing buffer contents were restored
	         } while (bs.contentsRestored());
        	// Display the buffer
        	bs.show();
        	// Repeat the rendering if the drawing buffer was lost
     	} while (bs.contentsLost());
		}
		/*else 
		{
			double size = (double)getWidth()/Board.getMap().getWidth();
			tile_size = (int) size;
			Board.TILE_SIZE = (int) size;
		}*/
	}

	
	
	/*public void validate(){
		super.validate();
	    new_size.width = getWidth();
	    new_size.height = getHeight();
	    if (old_size.equals(new_size)) {
	        return;
	    } else {
	        render();
	    }
	}*/
	
	
	/*protected synchronized void render() {
	
		int height = getHeight();
		int width = getWidth();
		
		do {
        	// The following loop ensures that the contents of the drawing buffer
        	// are consistent in case the underlying surface was recreated
        	do {
        		// Get a new graphics context every time through the loop
        		// to make sure the strategy is validated
        		Graphics graphics = bs.getDrawGraphics();
        		graphics.clearRect(0,0,width, height);
        		graphics.setColor(new Color(255, 0, 0));
	            graphics.setFont(new Font(Font.DIALOG, 50, 50));
	             
	             graphics.drawString("Pregrałeś!", width/10, height/10);
	             System.out.println("Jestem w funkcji render()");
        		
        		//repaint((int)(initialPosition)*TILE_SIZE, (int)(map.getPlayer().getY())*TILE_SIZE, 3*64, 64);//updateOffscreen(graphics);// Render to graphics sprobowac repaintem
        		graphics.dispose(); // Dispose the graphics

        		// Repeat the rendering if the drawing buffer contents were restored
	         } while (bs.contentsRestored());
        	// Display the buffer
        	bs.show();
        	// Repeat the rendering if the drawing buffer was lost
     	} while (bs.contentsLost());
		
	}*/

	/*public void updateOffscreen(Graphics g){
		
		g.setColor(new Color(255, 0, 0));
        g.setFont(new Font(Font.DIALOG, 50, 50));
		g.drawString("Tutaj beda informacje", 0,0);
		
	}*/
	
/*public void paint(Graphics g){
		
		g.setColor(new Color(255, 0, 0));
        g.setFont(new Font(Font.DIALOG, 50, 50));
		g.drawString("Tutaj beda informacje", 0,0);
		
	}*/
	
	
	
	
	
	
		
		
		
		//if (RunnableGetImage.completed==true) f.removeKeyListener(f);
		/*if (f.seconds == 0){
			f.p1.updateDescription(60, f.trialsNo-1, )
		}*/
		/*TextField time = new TextField(2);
		TextField trials = new TextField(1);
		TextField lev = new TextField(1);
		time.setEnabled(false);
		lev.setEnabled(false);
		trials.setEnabled(false);
		Label Ltime = new Label("Pozostały czas: ");
		Label Llev = new Label("Numer poziomu: ");
		Label Ltrials = new Label("Liczba pozostałych prób: ");
		Panel p1 = new Panel(new FlowLayout());
		p1.add(Ltime);
		p1.add(time);
		p1.add(Llev);
		p1.add(lev);
		p1.add(Ltrials);
		p1.add(trials);
		f.add(p1);*/
		
		/*repaint();
		f.render();*/
		
		
		//Panel panel = new Panel()
		/*TextArea text = new TextArea("Text to display",1,10);
		f.add(text, BorderLayout.North);*/
		
        /*Scanner s = null;
        int screenWidth = 0;
        int screenHeight = 0;

        try {
        	
            s = new Scanner(new BufferedReader(new FileReader("Config.txt")));
   
            screenWidth=s.nextInt();
            screenHeight=s.nextInt();
            
        
        }
        
        finally {
            s.close();
        }*/
        
		
        
    
 
    //end of main
	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void componentHidden(ComponentEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void componentMoved(ComponentEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void componentShown(ComponentEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	

	

	

	/*@Override
	public void mouseClicked(MouseEvent e) {
	
		System.out.println("mouseClicked!");
		
			if (e.getSource() == choiceButtons.restartButton)  
			{
				gameFailed=false;
				levelCompleted=false;
				RunnableGetImage.completed=false;
				restartGame();
				(t = new Thread(this)).start();
			}
			else if (e.getSource() == choiceButtons.restartButton)
			{
				RunnableGetImage.completed = false;
				levelCompleted=false;
				advanceLevel();
				(t = new Thread(this)).start();
			}
			else if (e.getSource() == connectionButtons.localButton){
				Main.internetConnection = false;
				gameStarted  = true;
				restartGame();
				(t = new Thread(this)).start();
			}
			else if (e.getSource() == connectionButtons.netButton){
				Main.internetConnection = true;
				gameStarted = true;
				restartGame();
				(t = new Thread(this)).start();
			}

	}*/

	@Override
	public void actionPerformed(ActionEvent ae) {
		
		if (ae.getActionCommand().equals(connectionButtons.localButton.getLabel())){
			Main.internetConnection = false;
			System.out.println("Gra lokalna");
			gameStarted  = true;
			restartGame();
			(t = new Thread(this)).start();
		}
		else if (ae.getActionCommand().equals(connectionButtons.netButton.getLabel())){
			Main.internetConnection = true;
			System.out.println("Gra sieciowa");
			gameStarted = true;
			restartGame();
			(t = new Thread(this)).start();
		}
		else if (ae.getActionCommand().equals(choiceButtons.restartButton.getLabel())){
		
			gameFailed=false;
			levelCompleted=false;
			RunnableGetImage.completed=false;
		
				restartGame();
			
			(t = new Thread(this)).start();
		}
		else if (ae.getActionCommand().equals(choiceButtons.nextButton.getLabel())){
		
			RunnableGetImage.completed = false;
			levelCompleted=false;
			advanceLevel();
			(t = new Thread(this)).start();
		}
		
	}

	
	

	/*private void render() {
		
		do {
        	// The following loop ensures that the contents of the drawing buffer
        	// are consistent in case the underlying surface was recreated
        	do {
        		// Get a new graphics context every time through the loop
        		// to make sure the strategy is validated
        		Graphics graphics = bs.getDrawGraphics();
        		updateOffscreen(graphics);
        		//repaint((int)(initialPosition)*TILE_SIZE, (int)(map.getPlayer().getY())*TILE_SIZE, 3*64, 64);//updateOffscreen(graphics);// Render to graphics sprobowac repaintem
        		graphics.dispose(); // Dispose the graphics

        		// Repeat the rendering if the drawing buffer contents were restored
	         } while (bs.contentsRestored());
        	// Display the buffer
        	bs.show();
        	// Repeat the rendering if the drawing buffer was lost
     	} while (bs.contentsLost());
		
	}*/	
	}//end of class


	
	


	


	
	